﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Player;
using VideoFile;
using AlarmManager;
using IAlarm;
using IAnalyze;
using System.Drawing.Drawing2D;
using VirtualControl;
using VideoConfig;

namespace Player
{
    /// <summary>
    /// 用户播放器控件
    ///     动态加载指定区域和设备的年月日信息
    ///     动态加载指定日期录像和报警信息
    ///     打开指定录像或报警
    ///     对录像或报警进行连续播放
    /// </summary>
    public class UserPlayer : PlayerBase
    {
        

        #region 公有属性
        [Category("播放器")]
        [Description("录像区域名称")]
        public new string Area { get; set; }

        [Category("播放器")]
        [Description("录像设备名称")]
        public new string Device { get; set; }
        #endregion

        #region 构造方法
        string recordPath, eventPath;

        private IContainer components;

        public UserPlayer()
            : base()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);

            InitializeComponent();

            InitializeVirtualControl();
        }

        public UserPlayer(string area, string device)
            : this()
        {
            this.Area = area;
            this.Device = device;
            this.recordPath = FileConfigReader.SingleConfig[area, device]["record"];
            this.eventPath = FileConfigReader.SingleConfig[area, device]["event"];
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            List<int> years = FilePath.GetYears(this.Area, this.Device, this.recordPath,this.eventPath);
            foreach (int year in years)
            {
                dateAxis.Years.Add(year);
            }

        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.tAlarm = new System.Windows.Forms.Timer(this.components);
            this.tPlayer = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            // 
            // tAlarm
            // 
            this.tAlarm.Interval = 1000;
            this.tAlarm.Tick += new System.EventHandler(this.tAlarm_Tick);
            // 
            // tPlayer
            // 
            this.tPlayer.Interval = 200;
            this.tPlayer.Tick += new System.EventHandler(this.tPlayer_Tick);
            // 
            // UserPlayer
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.Name = "UserPlayer";
            this.Size = new System.Drawing.Size(352, 288);
            this.ResumeLayout(false);

        }

        #endregion

        #region 时间检索
        void virtualDateAxis_YearChanged(object sender, EventArgs e)
        {
            List<int> months = FilePath.GetMonths(this.Area, this.Device, dateAxis.Year, this.recordPath, this.eventPath);
            foreach (int month in months)
            {
                dateAxis.Months.Add(month);
            }
        }

        void virtualDateAxis_MonthChanged(object sender, EventArgs e)
        {
            List<int> days = FilePath.GetDays(this.Area, this.Device, dateAxis.Year, dateAxis.Month, this.recordPath, this.eventPath);
            foreach (int day in days)
            {
                dateAxis.Days.Add(day);
            }
        }

        private Timer tPlayer;

        Dictionary<DateTime, GroupInfo> DGroups = new Dictionary<DateTime, GroupInfo>();
        void virtualDateAxis_DayChanged(object sender, EventArgs e)
        {
            DateTime[] timeRecords = GetAreaDeviceDateRecords(this.Area, this.Device, dateAxis.Value);
            this.timeAxis.TimeAxisItems[0].Clear();

            Player.PlayerBase player = null;
            foreach (DateTime time in timeRecords)
            {
                string recordInfo = FilePath.GetDatePathTimeFile(this.recordPath, this.Area, this.Device, time, "record");
                string recordFile = FilePath.GetDatePathTimeFile(this.recordPath, this.Area, this.Device, time, "mp4");
                if (File.Exists(recordInfo))
                {
                    using (StreamReader SR = File.OpenText(recordInfo))
                    {
                        this.timeAxis.TimeAxisItems[0].Add(time, TimeSpan.Parse(SR.ReadLine()));
                        Application.DoEvents();
                    }
                }
                else if (File.Exists(recordFile))
                {
                    if (player == null) player = new Player.PlayerBase();
                    player.Open(this.Area, this.Device, time);
                    using (StreamWriter SW = File.CreateText(recordInfo))
                    {
                        SW.WriteLine(player.TotalTime.ToString());
                    }
                    this.timeAxis.TimeAxisItems[0].Add(time, player.TotalTime);
                    player.Close();
                    Application.DoEvents();
                }
                
            }
            if (player != null) player.Dispose();

            FileAlarmReader alarmReader = new FileAlarmReader();
            GroupInfo[] groups = alarmReader.ReadGroups(this.Area, this.Device, dateAxis.Value);
            this.timeAxis.TimeAxisItems[1].Clear();
            DGroups.Clear();
            foreach (var item in groups)
            {
                if (item.AlarmCount > 0)
                {
                    this.timeAxis.TimeAxisItems[1].Add(item.GroupTime, new TimeSpan(0));
                    DGroups.Add(item.GroupTime, item);
                    Application.DoEvents();
                }
            }
            timeAxis.ZoomReset();
        }

        void virtualTimeAxis_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (timeAxis.CurrentItem != DateTime.MinValue)
            {
                switch (timeAxis.TimeAxisIndex)
                {
                    case 0:
                        PlayRecord(timeAxis.CurrentItem);
                        break;
                    case 1:
                        PlayAlarm(timeAxis.CurrentItem);
                        this.Invalidate();
                        break;
                }
            }
        }

        void virtualBase_Invalidated(object sender, EventArgs e)
        {
            if (!this.isPlayRecord)
            {
                VirtualBase vb = sender as VirtualBase;
                this.Invalidate(vb.Bounds);
            }
        }
        #endregion

        #region 虚拟界面
        void InitializeVirtualControl()
        {
            VirtualTimeAxis.TimeAxisType[] types = new VirtualTimeAxis.TimeAxisType[2];
            types[0] = VirtualTimeAxis.TimeAxisType.Rectangle;
            types[1] = VirtualTimeAxis.TimeAxisType.Linear;
            timeAxis = new VirtualTimeAxis(this, types, new Color[] { Color.Red, Color.Lime });
            timeAxis.Bounds = new Rectangle(0, this.Height - 30, this.Width - 1, 30);
            timeAxis.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            timeAxis.Invalidated += new EventHandler(virtualBase_Invalidated);
            timeAxis.MouseDoubleClick += new EventHandler<MouseEventArgs>(virtualTimeAxis_MouseDoubleClick);

            dateAxis = new VirtualDateAxis(this);
            dateAxis.Bounds = new Rectangle(0, this.Height - 50, this.Width - 1, 20);
            dateAxis.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            dateAxis.Invalidated += new EventHandler(virtualBase_Invalidated);
            dateAxis.YearChanged += new EventHandler(virtualDateAxis_YearChanged);
            dateAxis.MonthChanged += new EventHandler(virtualDateAxis_MonthChanged);
            dateAxis.DayChanged += new EventHandler(virtualDateAxis_DayChanged);

            VHSchedule = new VirtualHScroll(this);
            VHSchedule.Bounds = new Rectangle(0, this.Height - 70 + 1, this.Width - 1, 18);
            VHSchedule.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            VHSchedule.VisibleBinding = GetPlayVisible;
            VHSchedule.Scroll += new EventHandler(VHSchedule_Scroll);

            VBClose = new VirtualButton(this);
            VBClose.Bounds = new Rectangle(this.Width - 40, 1, 38, 18);
            VBClose.Anchor = AnchorStyles.Top | AnchorStyles.Right;
            VBClose.Text = "视频";
            VBClose.Invalidated += new EventHandler(virtualBase_Invalidated);
            VBClose.MouseClick += new EventHandler<MouseEventArgs>(VBClose_MouseClick);

            VBTitle = new VirtualButton(this);
            VBTitle.Bounds = new Rectangle(1, 1, 0, 0);
            VBTitle.AutoSize = true;
            VBTitle.TextBinding = GetTitleText;
            VBTitle.Enabled = false;

            VBStartTime = new VirtualButton(this);
            VBStartTime.Bounds = new Rectangle(0, this.Bounds.Height - 90, 60, 20);
            VBStartTime.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
            VBStartTime.VisibleBinding = GetPlayVisible;

            VBEndTime = new VirtualButton(this);
            VBEndTime.Bounds = new Rectangle(this.Bounds.Width - 60 - 1, this.Bounds.Height - 90, 60, 20);
            VBEndTime.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            VBEndTime.VisibleBinding = GetPlayVisible;

            VBCurrentTime = new VirtualButton(this);
            VBCurrentTime.Bounds = new Rectangle((this.Bounds.Width - 60) / 2, this.Bounds.Height - 90, 60, 20);
            VBCurrentTime.Anchor = AnchorStyles.Bottom;
            VBCurrentTime.VisibleBinding = GetPlayVisible;

        }

        void VHSchedule_Scroll(object sender, EventArgs e)
        {
            if (this.isPlayRecord)
            {
                this.PlayPosition = VHSchedule.Value / 100;
            }
        }

        void VBClose_MouseClick(object sender, MouseEventArgs e)
        {
            tAlarm.Stop();
            tPlayer.Stop();
            this.Hide();
            this.Close();
            isPlayRecord = false;
            this.Invalidate();
        }

        string GetTitleText()
        {
            return string.Format("{0}-{1}", this.Area, this.Device);
        }

        bool GetPlayVisible()
        {
            return this.isPlayRecord;
        }

        VirtualHScroll VHSchedule;      //进度条
        VirtualButton VBClose;          //关闭按钮
        VirtualButton VBTitle;          //标题栏
        VirtualButton VBStartTime;      //起始时间
        VirtualButton VBEndTime;        //结束时间
        VirtualButton VBCurrentTime;    //当前时间
        VirtualTimeAxis timeAxis;       //时间轴
        VirtualDateAxis dateAxis;       //日期轴
        #endregion

        #region 播放控制
        private Timer tAlarm;
        bool isPlayRecord = false;
        private void PlayRecord(DateTime datetime)
        {
            tAlarm.Stop();
            tPlayer.Stop();
            group = null;
            this.Open(this.Area, this.Device, datetime);
            this.VBStartTime.Text = this.StartTime.ToString("HH:mm:ss");
            this.VBEndTime.Text = (this.StartTime + this.TotalTime).ToString("HH:mm:ss");
            isPlayRecord = true;
            this.Play();
            tPlayer.Start();
        }

        private void PlayAlarm(DateTime datetime)
        {
            this.Close();
            isPlayRecord = false;
            tAlarm.Stop();
            tPlayer.Stop();
            lock (this)
            {
                indexAlarm = 0;
                group = DGroups[datetime];
            }
            tAlarm.Start();
        }

        GroupInfo group = null;
        int indexAlarm = 0;
        FileAlarmReader alarmReader = new FileAlarmReader();
        private void tAlarm_Tick(object sender, EventArgs e)
        {
            lock (this)
            {
                indexAlarm = (++indexAlarm) % group.AlarmCount;
                if (!this.isPlayRecord) this.Invalidate();
            }
        }


        private void tPlayer_Tick(object sender, EventArgs e)
        {
            if (this.isPlayRecord)
            {
                VHSchedule.Value = this.PlayPosition * 100;
                this.VBCurrentTime.Text = (this.StartTime + this.PlayedTime).ToString("HH:mm:ss");
            }

        }

        protected override void OnPlayEnd(EventArgs e)
        {
            base.OnPlayEnd(e);

            this.Close();
            isPlayRecord = false;
            tPlayer.Stop();
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);

            if (e.Y < this.Height - 90 && e.X > 20 && this.isPlayRecord)
            {
                if (this.Player.PlayState == IPlayer.PlayStateEnum.Play)
                    this.Pause();
                else if (this.Player.PlayState == IPlayer.PlayStateEnum.Pause)
                    this.Play();
            }
        }
        #endregion

        #region 界面绘图
        protected override void OnPlayerPaint(IPlayer.EventArgsPaint e)
        {
            base.OnPlayerPaint(e);


            PlayerPaint(e.Graphics);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (!this.isPlayRecord)
            {
                base.OnPaint(e);

                PlayerPaint(e.Graphics);
            }

        }

        void PlayerPaint(Graphics G)
        {
            #region 绘制报警帧
            if (!this.isPlayRecord && group != null)
            {
                lock (this)
                {
                    AlarmInfo alarm = group[indexAlarm];

                    Bitmap frame = alarmReader.ReadFrame(group, alarm);
                    Size sizeFrame = frame.Size;
                    G.DrawImage(frame, 0, 0, this.Width, this.Height);
                    frame.Dispose();

                    //float w = (float)this.Width / (float)sizeFrame.Width;
                    //float h = (float)this.Height / (float)sizeFrame.Height;

                    float w = (float)this.Width / 704;
                    float h = (float)this.Height / 576;
                    for (int i = 0; i < alarm.AlarmRegion.Length; i++)
                    {
                        RectangleF rectAlarm = new RectangleF(
                            alarm.AlarmRegion[i].X * w,
                            alarm.AlarmRegion[i].Y * h,
                            alarm.AlarmRegion[i].Width * w,
                            alarm.AlarmRegion[i].Height * h);
                        Color colorAlarm = Color.FromArgb(
                            ((AlarmRegionEnum)alarm.AlarmRegionType[i] & AlarmRegionEnum.Fire) == AlarmRegionEnum.Fire ? 255 : 0,
                            ((AlarmRegionEnum)alarm.AlarmRegionType[i] & AlarmRegionEnum.Smoke) == AlarmRegionEnum.Smoke ? 255 : 0,
                            ((AlarmRegionEnum)alarm.AlarmRegionType[i] & AlarmRegionEnum.Motion) == AlarmRegionEnum.Motion ? 255 : 0);

                        using (Pen penAlarm = new Pen(colorAlarm))
                        {
                            VirtualBase.DrawRectangle(G, penAlarm, Rectangle.Round(rectAlarm));
                        }

                    }
                }
            }

            #endregion

            VirtualBase.VirtualPaint(this, G);
        }

        #endregion

    }
}
